package com.hucheng.activity.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hucheng.activity.entity.LuckPrizeDetailsDO;
import com.hucheng.activity.mapper.LuckPrizeDetailsMapper;
import com.hucheng.activity.mapper.LuckPrizeMapper;
import com.hucheng.activity.mapper.UserPointMapper;
import com.hucheng.activity.query.LuckPrizeDetailsQuery;
import com.hucheng.activity.query.LuckPrizeQuery;
import com.hucheng.activity.service.LuckPrizeService;
import com.hucheng.activity.service.UserPointActivityService;
import com.hucheng.activity.utils.LuckPrizeUtils;
import com.hucheng.activity.vo.LuckPrizeVO;
import com.hucheng.activity.vo.PrizeVO;
import com.hucheng.activity.vo.UserPointVO;
import com.hucheng.common.constant.RedisConstant;
import com.hucheng.common.exception.EduException;
import com.hucheng.common.page.CommonPager;
import com.hucheng.common.page.PageParameter;
import com.hucheng.common.utils.RedisUtils;
import com.hucheng.common.utils.ValidatorUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: 凉白开不加冰
 * @Version: 0.0.1V
 * @Date: 2019-07-10
 * @Description: 抽奖实现类
 **/
@Component
@Service(interfaceClass = LuckPrizeService.class, retries = -1, timeout = 5000)
public class LuckPrizeServiceImpl implements LuckPrizeService {

    @Autowired
    private LuckPrizeMapper luckPrizeMapper;

    @Autowired
    private LuckPrizeDetailsMapper luckPrizeDetailsMapper;

    @Autowired
    private UserPointMapper userPointMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserPointActivityService userPointActivityService;

    @Override
    public CommonPager<LuckPrizeVO> list(LuckPrizeQuery luckPrizeQuery) {
        return new CommonPager<>(new PageParameter(
                luckPrizeQuery.getPageParameter().getCurrentPage(),
                luckPrizeQuery.getPageParameter().getPageSize(),
                luckPrizeMapper.count(luckPrizeQuery)),
                luckPrizeMapper.list(luckPrizeQuery).stream().map(LuckPrizeVO::buildLuckPrizeVO).collect(Collectors.toList()));
    }

    @Override
    public void initLuckPrizeList(LuckPrizeQuery luckPrizeQuery) {
        List<LuckPrizeVO> list = luckPrizeMapper.list(luckPrizeQuery).stream().map(LuckPrizeVO::buildLuckPrizeVO).collect(Collectors.toList());
        list.forEach(luckPrizeVO -> {
            RedisUtils.set(stringRedisTemplate, RedisConstant.LUCK_PRIZE_KEY + luckPrizeVO.getLuckPrizeConfigId(), JSONObject.toJSONString(luckPrizeVO));
        });
    }

    @Override
    public PrizeVO luckPrize(Integer userId, Integer luckPrizeConfigId) throws EduException {
        //获取活动配置
        String prizeInfo = RedisUtils.getString(stringRedisTemplate, RedisConstant.LUCK_PRIZE_KEY + luckPrizeConfigId);
        if (prizeInfo == null || ValidatorUtils.isEmpty(prizeInfo)) {
            //去数据库拿去活动配置
            LuckPrizeQuery luckPrizeQuery = new LuckPrizeQuery();
            luckPrizeQuery.setStatus(1);
            luckPrizeQuery.setLuckPrizeConfigId(luckPrizeConfigId);
            LuckPrizeVO luckPrizeVO = LuckPrizeVO.buildLuckPrizeVO(luckPrizeMapper.get(luckPrizeQuery));
            prizeInfo = JSONObject.toJSONString(luckPrizeVO);
            if (luckPrizeVO != null) {
                RedisUtils.set(stringRedisTemplate, RedisConstant.LUCK_PRIZE_KEY + luckPrizeVO.getLuckPrizeConfigId(), JSONObject.toJSONString(luckPrizeVO));
            }
        }
        //判断活动是否开始及结束
        JSONObject luckInfo = JSONObject.parseObject(prizeInfo);
        if (luckInfo == null) {
            throw new EduException(140000);
        }
        checkLuckPrizeStatus(luckInfo.getDate("dateStart"), luckInfo.getDate("dateEnd"));
        //判断用户以抽奖次数
        int freeCount = luckInfo.getInteger("freeCount");
        int limitCount = luckInfo.getInteger("limitCount");
        int point = luckInfo.getInteger("point");
        LuckPrizeDetailsQuery luckPrizeDetailsQuery = new LuckPrizeDetailsQuery();
        luckPrizeDetailsQuery.setLuckPrizeConfigId(luckPrizeConfigId);
        luckPrizeDetailsQuery.setUserId(userId);
        int luckCount = luckPrizeDetailsMapper.count(luckPrizeDetailsQuery);
        if (limitCount > 0 && luckCount >= limitCount) {
            throw new EduException(140002);
        }
        //用户是否存在免费、活动是否有免费抽奖次数
        UserPointVO userPointVO = UserPointVO.buildUserPointVO(userPointMapper.get(userId));
        boolean isPoint = false;
        if (freeCount == 0) {
            isPoint = true;
        } else if (luckCount >= freeCount) {
            isPoint = true;
        }
        if (isPoint) {
            //判断用户积分是否足够
            if (userPointVO == null) {
                throw new EduException(150000);
            }
            if (userPointVO.getPoint() < point) {
                throw new EduException(150000);
            }
            userPointActivityService.subtractPoint(point, luckInfo.getString("luckPrizeConfigName"), userId);
        }

        //抽奖
        JSONObject luckPrizeRemark = luckInfo.getJSONObject("luckPrizeRemark");
        JSONArray prizeList = luckPrizeRemark.getJSONArray("prize_list");
        List<PrizeVO> list = prizeList.toJavaList(PrizeVO.class);
        int index = LuckPrizeUtils.getPrizeIndex(list);

        PrizeVO prizeVO = list.get(index);
        //插入抽奖记录
        LuckPrizeDetailsDO luckPrizeDetailsDO = new LuckPrizeDetailsDO();
        luckPrizeDetailsDO.setIsDel(0);
        luckPrizeDetailsDO.setLuckPrizeConfigId(luckPrizeConfigId);
        luckPrizeDetailsDO.setUserId(userId);
        luckPrizeDetailsDO.setPrizeName(prizeVO.getPrizeName());
        luckPrizeDetailsMapper.insert(luckPrizeDetailsDO);

        return prizeVO;
    }

    private void checkLuckPrizeStatus(Date start, Date end) throws EduException {
        Date date = new Date();
        if (date.getTime() < start.getTime()) {
            //秒杀未开始
            throw new EduException(140001);
        } else if (date.getTime() > end.getTime()) {
            //秒杀结束
            throw new EduException(140000);
        }
    }
}
